﻿#region Copyright 
/*-------------------------------------------------------------------------
* 命名空间名称/文件名:    SSPivot.Admin.Core.Service.sys.Permission/SysPermissionServiceImpl 
* CLR版本:     4.0.30319.42000
* 机器名称:    DESKTOP-NHMLO8A
* 功 能：       N/A
* 类 名：       SysPermissionServiceImpl
* 创建时间：  2025/6/4 17:36:14
* 版本号：      v1.0
* 创建人:        xulong
*-------------------------------------------------------------------------*/
#endregion
using DotNetCore.CAP.Dashboard;
using Mapster;
using MapsterMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using NPOI.OpenXmlFormats.Wordprocessing;
using SSPivot.Admin.Core.DbModel.sys;
using SSPivot.Admin.Core.Repository;
using SSPivot.Admin.Core.Service.sys.Permission.Dto;
using SSPivot.AspNetCore.Abstractions.User;
using SSPivot.AspNetCore.Services;
using SSPivot.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace SSPivot.Admin.Core.Service.sys.Permission
{
    /// <summary>
    /// 权限服务
    /// </summary>
    public class SysPermissionServiceImpl : ApplicationService, ISysPermissionService
    {
        #region 接口注入
        private ISSPivotRepository<sys_permission> PermissionRep { get; set; } 
        private Lazy<ISSPivotRepository<sys_role>> RoleRep { get; set; }
        private Lazy<ISSPivotRepository<sys_user>> UserRep { get; set; }
        private Lazy<ISSPivotRepository<sys_role_permission>> RolePermissionRep { get; set; } 
        private Lazy<ISSPivotRepository<sys_user_role>> UserRoleRep { get; set; }     
        public SysPermissionServiceImpl(
            ISSPivotRepository<sys_permission> permissionRep, 
            Lazy<ISSPivotRepository<sys_role>> roleRep,
            Lazy<ISSPivotRepository<sys_user>> userRep,
            Lazy<ISSPivotRepository<sys_role_permission>> rolePermissionRep, 
            Lazy<ISSPivotRepository<sys_user_role>> userRoleRep
        )
        {
            PermissionRep = permissionRep; 
            RoleRep = roleRep;
            UserRep = userRep;
            RolePermissionRep = rolePermissionRep; 
            UserRoleRep = userRoleRep; 
        }

        #endregion

        #region 服务
        /// <summary>
        /// 清除权限下关联的用户权限缓存
        /// </summary>
        /// <param name="permissionIds"></param>
        /// <returns></returns>
        private async Task ClearUserPermissionsAsync(List<long> permissionIds)
        {
            var roleIds = await RolePermissionRep.Value.QueryNoTracking(e => permissionIds.Contains(e.PermissionId)).Select(e => e.RoleId).ToListAsync();
            var userIds = await UserRoleRep.Value.QueryNoTracking(e => roleIds.Contains(e.RoleId)).Select(e => e.UserId).ToListAsync();
            foreach (var item in userIds)
            {
                await Cache.RemoveAsync($"{GlobalConfig.CacheKeys.UserPermission}{item}");
            }
        }

        /// <summary>
        /// 查询分组
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<PermissionGetGroupDto> GetGroupAsync(long id)
        {
            var result = await PermissionRep.GetAsync(id);
            return result.Adapt<PermissionGetGroupDto>();
        }

        /// <summary>
        /// 查询菜单
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<PermissionGetMenuDto> GetMenuAsync(long id)
        {
            var data = await PermissionRep.GetAsync(id);
            return data.Adapt<PermissionGetMenuDto>();
        }

        /// <summary>
        /// 查询权限点
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<PermissionGetDotDto> GetDotAsync(long id)
        {
            var data = await PermissionRep.GetAsync(id);
            var result = data.Adapt<PermissionGetDotDto>();
            //result.ApiIds = await PermissionApiRep.QueryNoTracking(e => e.PermissionId == data.Id).OrderBy(a => a.Id).Select(e => e.ApiId).ToListAsync();
            return result;
        }

        /// <summary>
        /// 查询权限列表
        /// </summary>
        /// <param name="key"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public async Task<List<PermissionListDto>> GetListAsync(QuerySysPermissionRequest model)
        {
            var data = await PermissionRep.QueryNoTracking(this.BuildSearch(model), this.BuildSort(model)).ToListAsync();
            var result = data.Adapt<List<PermissionListDto>>();
            foreach (var item in data)
            {
                var view = item.Adapt<PermissionListDto>();
                //view.ViewPath = await ViewRep.Value.QueryNoTracking(e => e.Id == item.ViewId).Select(e => e.Path).FirstOrDefaultAsync();
                //var papiIds = await PermissionApiRep.Query(e => e.PermissionId == item.Id).OrderBy(a => a.Id).Select(e => e.ApiId).ToListAsync();
                //view.ApiPaths = (await ApiRep.Value.QueryNoTracking(e => papiIds.Contains(e.Id)).Select(e => e.Path).ToListAsync()).Join();
                result.Add(view);
            }
            return result;
        }
        /// <summary>
        /// 查询授权权限列表
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<dynamic>> GetPermissionListAsync()
        {
            if (User.Type == UserType.DefaultUser || User.Type == UserType.Member) return null;
            var pQuery = PermissionRep.Query(e => e.Enabled == true);

            //if (AppConfig.Value.Value.Tenant && User.Type == UserType.TenantAdmin)
            //{
            //    var tenantPermissionIds = await TenantPermissionRep.Value.QueryNoTracking(e => e.Id == User.TenantId).Select(e => e.PermissionId).ToListAsync();
            //    var tenantPkgIds = await TenantPkgRep.Value.QueryNoTracking(e => e.TenantId == User.TenantId).Select(e => e.PkgId).ToListAsync();
            //    var pkgPermissionPermissionIds = await PkgPermissionRep.Value.QueryNoTracking(e => tenantPkgIds.Contains(e.PkgId)).Select(e => e.PermissionId).ToListAsync();
            //    pQuery = pQuery.Where(e => tenantPermissionIds.Contains(e.Id) || pkgPermissionPermissionIds.Contains(e.Id));
            //}
            var permissions = await pQuery.Select(e => new
            {
                e.Id,
                e.ParentId,
                e.Label,
                e.Type,
                e.Sort

            }).ToListAsync();

            var menus = permissions.DistinctBy(a => a.Id).OrderBy(a => a.ParentId).ThenBy(a => a.Sort)
                .Select(a => new
                {
                    a.Id,
                    a.ParentId,
                    a.Label,
                    Row = a.Type == PermissionType.Menu
                });

            return menus;
        }

        /// <summary>
        /// 查询角色权限列表
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public async Task<List<long>> GetRolePermissionListAsync(long roleId = 0)
        {
            return await RolePermissionRep.Value.QueryNoTracking(e => e.RoleId == roleId).Select(e => e.PermissionId).ToListAsync();

        }

        ///// <summary>
        ///// 查询租户权限列表
        ///// </summary>
        ///// <param name="tenantId"></param>
        ///// <returns></returns>
        //[Obsolete("请使用查询套餐权限列表PkgService.GetPkgPermissionListAsync")]
        //public async Task<List<long>> GetTenantPermissionListAsync(long tenantId)
        //{
        //    return await TenantPermissionRep.Value.QueryNoTracking(e => e.TenantId == tenantId).Select(e => e.PermissionId).ToListAsync();

        //}
        /// <summary>
        /// 新增分组
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<long> AddGroupAsync(PermissionAddGroupDto input)
        {
            var entity = Mapper.Map<sys_permission>(input);
            entity.Type = PermissionType.Group;

            if (entity.Sort == 0)
            {
                var sort = await PermissionRep.QueryNoTracking(a => a.ParentId == input.ParentId).MaxAsync(a => a.Sort);
                entity.Sort = sort + 1;
            }
            await SetParentsValue(entity);
            await PermissionRep.AddAsync(entity);
            return entity.Id;
        }

        /// <summary>
        /// 新增菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<long> AddMenuAsync(PermissionAddMenuDto input)
        {
            var entity = Mapper.Map<sys_permission>(input);
            entity.Type = PermissionType.Menu;
            if (entity.Sort == 0)
            {
                var sort = await PermissionRep.QueryNoTracking(a => a.ParentId == input.ParentId).MaxAsync(a => a.Sort);
                entity.Sort = sort + 1;
            }
            await SetParentsValue(entity);
            await PermissionRep.AddAsync(entity);

            return entity.Id;
        }
        /// <summary>
        /// 新增接口
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<long> AddApiAsync(PermissionAddApiDto input)
        {
            var entity = Mapper.Map<sys_permission>(input);
            entity.Type = PermissionType.Dot;
            if (entity.Sort == 0)
            {
                var sort = await PermissionRep.QueryNoTracking(a => a.ParentId == input.ParentId).MaxAsync(a => a.Sort);
                entity.Sort = sort + 1;
            }
            await SetParentsValue(entity);
            await PermissionRep.AddAsync(entity);

            return entity.Id;
        }

        /// <summary>
        /// 新增权限点
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns> 
        public virtual async Task<long> AddDotAsync(PermissionAddDotDto model)
        {
            var entity = Mapper.Map<sys_permission>(model);
            entity.Type = PermissionType.Dot;
            if (entity.Sort == 0)
            {
                var sort = await PermissionRep.QueryNoTracking(a => a.ParentId == model.ParentId).MaxAsync(a => a.Sort);
                entity.Sort = sort + 1;
            }
            await SetParentsValue(entity);
            await PermissionRep.AddAsync(entity);

            //if (model.ApiIds != null && model.ApiIds.Any())
            //{
            //    var permissionApis = model.ApiIds.Select(a => new sys_permission_api { PermissionId = entity.Id, ApiId = a }).ToList();
            //    await PermissionApiRep.AddRangeAsync(permissionApis);
            //}

            return entity.Id;
        }

        /// <summary>
        /// 修改分组
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task UpdateGroupAsync(PermissionUpdateGroupDto input)
        {
            var entity = await PermissionRep.GetAsync(input.Id);
            entity = Mapper.Map(input, entity);
            await SetParentsValue(entity);
            await PermissionRep.UpdateAsync(entity);
        }


        /// <summary>
        /// 修改菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task UpdateMenuAsync(PermissionUpdateMenuDto input)
        {
            var entity = await PermissionRep.GetAsync(input.Id);
            entity = Mapper.Map(input, entity);
            await SetParentsValue(entity);
            await PermissionRep.UpdateAsync(entity);
        }

        /// <summary>
        /// 修改权限点
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns> 
        public virtual async Task UpdateDotAsync(PermissionUpdateDotDto input)
        {
            var entity = await PermissionRep.GetAsync(input.Id);
            if (!(entity?.Id > 0))
            {
                throw ServiceResult.Exception("权限点不存在");
            }

            Mapper.Map(input, entity);
            await SetParentsValue(entity);
            await PermissionRep.UpdateAsync(entity);
            //await PermissionApiRep.Query(a => a.PermissionId == entity.Id).DeleteAsync();

            //if (input.ApiIds != null && input.ApiIds.Any())
            //{
            //    var permissionApis = input.ApiIds.Select(a => new sys_permission_api { PermissionId = entity.Id, ApiId = a });
            //    await PermissionApiRep.AddRangeAsync(permissionApis.ToList());
            //}

            //清除用户权限缓存
            await ClearUserPermissionsAsync(new List<long> { entity.Id });
        }

        /// <summary>
        /// 彻底删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>  
        public async Task DeleteAsync(long id)
        {
            //递归查询所有权限点
            var ids = await PermissionRep.QueryNoTracking(e => e.ParentIds.Contains(id.ToString())).Select(e => e.Id).ToListAsync();

            ////删除权限关联接口
            //await PermissionApiRep.QueryIgnoreQueryFilters(e => ids.Contains(e.PermissionId)).ExecuteDeleteAsync();

            //删除相关权限
            await PermissionRep.QueryIgnoreQueryFilters(a => ids.Contains(a.Id)).ExecuteDeleteAsync();

            //清除用户权限缓存
            await ClearUserPermissionsAsync(ids);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task SoftDeleteAsync(long id)
        {
            //递归查询所有权限点
            var ids = await PermissionRep.QueryNoTracking(e => e.ParentIds.Contains(id.ToString())).Select(e => e.Id).ToListAsync();
            //删除相关权限
            await PermissionRep.QueryIgnoreQueryFilters(a => ids.Contains(a.Id)).ExecuteDeleteAsync();

            //清除用户权限缓存
            await ClearUserPermissionsAsync(ids);
        }

        /// <summary>
        /// 保存角色权限
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>   
        public virtual async Task AssignAsync(PermissionAssignDto model)
        {
            if (User.Type == UserType.DefaultUser || User.Type == UserType.Member) return;
            //分配权限的时候判断角色是否存在
            if (!(await RoleRep.Value.QueryNoTracking(e => e.Id == model.RoleId).AnyAsync()))
            {
                throw ServiceResult.Exception("该角色不存在或已被删除");
            }

            //查询角色权限
            var permissionIds = await RolePermissionRep.Value.QueryNoTracking(d => d.RoleId == model.RoleId).Select(m => m.PermissionId).ToListAsync();

            //批量删除权限
            var deleteIds = permissionIds.Where(d => !model.PermissionIds.Contains(d));
            if (deleteIds.Any())
            {
                await RolePermissionRep.Value.Query(m => m.RoleId == model.RoleId && deleteIds.Contains(m.PermissionId)).ExecuteDeleteAsync();
            }

            //批量插入权限
            var insertRolePermissions = new List<sys_role_permission>();
            var insertPermissionIds = model.PermissionIds.Where(d => !permissionIds.Contains(d));

            //防止租户非法授权，查询主库租户权限范围
            //if (AppConfig.Value.Value.Tenant && User.Type == UserType.TenantAdmin)
            //{
            //    var tenantPermissionIds = await TenantPermissionRep.Value.QueryNoTracking(e => e.TenantId == User.TenantId).Select(e => e.PermissionId).ToListAsync();
            //    var tenantPkgPkgIds = await TenantPkgRep.Value.QueryNoTracking(e => e.TenantId == User.TenantId).Select(e => e.PkgId).ToListAsync();
            //    var pkgPermissionIds = await PkgPermissionRep.Value.QueryNoTracking(e => tenantPkgPkgIds.Contains(e.PkgId)).Select(e => e.PermissionId).ToListAsync();
            //    insertPermissionIds = insertPermissionIds.Where(d => tenantPermissionIds.Contains(d) || pkgPermissionIds.Contains(d));

            //}

            if (insertPermissionIds.Any())
            {
                foreach (var permissionId in insertPermissionIds)
                {
                    insertRolePermissions.Add(new sys_role_permission()
                    {
                        RoleId = model.RoleId,
                        PermissionId = permissionId,
                    });
                }
                await RolePermissionRep.Value.AddRangeAsync(insertRolePermissions);
            }

            //清除角色下关联的用户权限缓存
            var userIds = await UserRoleRep.Value.QueryNoTracking(a => a.RoleId == model.RoleId).Select(a => a.UserId).ToListAsync();
            foreach (var userId in userIds)
            {
                await Cache.RemoveAsync(GlobalConfig.CacheKeys.UserPermission + userId);
            }
        }

        /// <summary>
        /// 保存租户权限
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>    
        [Obsolete("请使用设置套餐权限PkgService.SetPkgPermissionsAsync")]
        public virtual async Task SaveTenantPermissionsAsync(PermissionSaveTenantPermissionsDto model)
        {
            if (User.Type == UserType.DefaultUser || User.Type == UserType.Member) return;
            ////查询租户权限
            //var permissionIds = await TenantPermissionRep.Value.QueryNoTracking(d => d.TenantId == model.TenantId).Select(m => m.PermissionId).ToListAsync();

            ////批量删除租户权限
            //var deleteIds = permissionIds.Where(d => !model.PermissionIds.Contains(d));
            //if (deleteIds.Any())
            //{
            //    await TenantPermissionRep.Value.Query(m => m.TenantId == model.TenantId && deleteIds.Contains(m.PermissionId)).ExecuteDeleteAsync();
            //    //删除租户下关联的角色权限
            //    await RolePermissionRep.Value.Query(a => deleteIds.Contains(a.PermissionId)).ExecuteDeleteAsync();
            //}

            ////批量插入租户权限
            //var tenatPermissions = new List<sys_tenant_permission>();
            //var insertPermissionIds = model.PermissionIds.Where(d => !permissionIds.Contains(d));
            //if (insertPermissionIds.Any())
            //{
            //    foreach (var permissionId in insertPermissionIds)
            //    {
            //        tenatPermissions.Add(new sys_tenant_permission()
            //        {
            //            TenantId = model.TenantId,
            //            PermissionId = permissionId,
            //        });
            //    }
            //    await TenantPermissionRep.Value.AddRangeAsync(tenatPermissions);
            //}

            ////清除租户下所有用户权限缓存 
            //var userIds = await UserRep.Value.QueryNoTracking(a => a.TenantId == model.TenantId).Select(a => a.Id).ToListAsync();
            //if (userIds.Any())
            //{
            //    foreach (var userId in userIds)
            //    {
            //        await Cache.RemoveAsync(CacheKeys.UserPermission + userId);
            //    }
            //}
        }
        #endregion

        #region tree

        /// <summary>
        /// 获得本级和下级Id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<long>> GetChildrenIdListAsync(long id)
        {

            return await PermissionRep.QueryNoTracking(e => e.ParentIds.Contains(id.ToString())).Select(e => e.Id).ToListAsync();

        }

        /// <summary>
        /// 获取上级
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<List<SysPermissionDto>> GetSupCategory(long id)
        {
            var result = new List<SysPermissionDto>();
            var info = await PermissionRep.GetAsync(id);
            var current = info.Adapt<SysPermissionDto>();
            if (current != null)
            {
                if (current.ParentId != 0)
                {
                    result.AddRange(await this.GetSupCategory(current.Id));
                }
                result.Add(current);
            }
            return result;
        }

        /// <summary>
        /// 获取上级名称
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<List<string>> GetSupCategoryName(long id)
        {
            var data = await this.GetSupCategory(id);
            return data.Select(e => e.Name).ToList();
        }

        /// <summary>
        /// 获取下级部门带层级
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<List<SysPermissionDto>> GetSubCategoryTreeAsync(QuerySysPermissionRequest model)
        {
            var result = new List<SysPermissionDto>();
            var query = PermissionRep.QueryNoTracking();
            if (model.ParentId.HasValue)
            {
                if (model.ContainSelf)
                    query = query.Where(e => e.Id == model.ParentId);
                else
                    query = query.Where(e => e.ParentId == model.ParentId);
            }
            else
            {
                query = query.Where(e => e.ParentId == 0);
            }
            var data = await query.ToListAsync();
            var listData = data.Adapt<List<SysPermissionDto>>();
            var allEntity = await PermissionRep.QueryNoTracking(e => true, e => e.Sort, SortType.Asc).ToListAsync();
            var allData = allEntity.Adapt<List<SysPermissionDto>>();
            foreach (var item in listData)
            {
                result.Add(RecursionCategory(item, allData));
            }
            return result;
        }

        /// <summary>
        /// 获取类别tree
        /// </summary>
        /// <returns></returns>
        public async Task<List<SysPermissionDto>> GetAllDataTreeAsync(QuerySysPermissionRequest model)
        {
            var allEntity = await PermissionRep.QueryNoTracking(this.BuildSearch(model), e => e.Sort, SortType.Asc).ToListAsync();
            var allData = allEntity.Adapt<List<SysPermissionDto>>();
            var mainData = allData.Where(e => e.ParentId == 0).ToList();
            var result = new List<SysPermissionDto>();
            foreach (var item in allData)
            {
                result.Add(RecursionCategory(item, allData));
            }

            return result;
        }
        /// <summary>
        /// 递归获取所有子级部门及层级
        /// </summary>
        /// <param name="model"></param>
        public SysPermissionDto RecursionCategory(SysPermissionDto model, List<SysPermissionDto> allData)
        {
            var childData = allData.Where(e => e.ParentId == model.Id).ToList();
            if (childData != null && childData.Count() > 0)
            {
                if (model.Children == null || model.Children.Count() == 0)
                    model.Children = new List<SysPermissionDto>();
                foreach (var child in childData)
                {
                    child.Level = model.Level + 1;
                    model.Children.Add(RecursionCategory(child, allData));
                }

            }
            return model;
        }
        #endregion

        #region private
        private Expression<Func<sys_permission, bool>> BuildSearch(QuerySysPermissionRequest model)
        {
            Expression<Func<sys_permission, bool>> whereCondition = e => true;

            if (model.Key.IsNotNullOrWhiteSpace())
                whereCondition = whereCondition.And(e => e.Path.Contains(model.Key) || e.Label.Contains(model.Key));
            if (model.SDate.HasValue)
                whereCondition = whereCondition.And(e => e.CreatedTime > model.SDate);
            if (model.EDate.HasValue)
            {
                var date = model.EDate.Value.AddDays(1);
                whereCondition = whereCondition.And(e => e.CreatedTime < date);
            }

            if (model.ParentId.HasValue)
            {
                if (model.ContainSelf)
                    whereCondition = whereCondition.And(e => e.Id == model.ParentId);
                else
                    whereCondition = whereCondition.And(e => e.ParentId == model.ParentId);
            }
            else
            {
                whereCondition = whereCondition.And(e => e.ParentId == 0);
            }
            return whereCondition;
        }

        private Dictionary<Expression<Func<sys_permission, dynamic>>, SortType> BuildSort(QuerySysPermissionRequest model)
        {
            var orderBy = new Dictionary<Expression<Func<sys_permission, dynamic>>, SortType>();
            orderBy.Add(e => e.ParentId, SortType.Asc);
            orderBy.Add(e => e.Sort, SortType.Asc);
            orderBy.Add(e => e.Id, SortType.Desc);
            return orderBy;
        }
        private async Task<sys_permission> SetParentsValue(sys_permission model)
        {
            if (model.ParentId == 0)
            {
                var pids = new List<long>() { model.Id };
                var names = new List<string>() { model.Name };
                model.ParentId = 0;
                model.ParentIds = pids.SerializeJson();
                model.ParentNames = names.SerializeJson();

            }
            else
            {
                var parent = (await PermissionRep.QueryNoTracking(x => x.Id == model.ParentId).FirstOrDefaultAsync());
                var parIds = parent.ParentIds.DeserializeJson<List<long>>();
                parIds.Add(model.Id);
                var parNames = parent.ParentNames.DeserializeJson<List<string>>();
                parNames.Add(model.Name);
                model.ParentName = parent.Name;
                model.ParentIds = parIds.SerializeJson();
                model.ParentNames = parNames.SerializeJson();
            }
            return model;
        }
        #endregion
    }
}
